home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / make.gy / part02 < prev    next >
Encoding:
Text File  |  1989-11-02  |  36.3 KB  |  1,303 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v08i105: Make Version 1.5 (Part 2 of 3)
  3. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  4. Reply-To: greggy@etude.UUCP (Greg Yachuk)
  5.  
  6. Posting-number: Volume 8, Issue 105
  7. Submitted-by: greggy@etude.UUCP (Greg Yachuk)
  8. Archive-name: make.gy/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 3)."
  17. # Contents:  make.doc parse.c
  18. # Wrapped by greggy@etude on Mon Oct 30 19:10:08 1989
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'make.doc' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'make.doc'\"
  22. else
  23. echo shar: Extracting \"'make.doc'\" \(17010 characters\)
  24. sed "s/^X//" >'make.doc' <<'END_OF_FILE'
  25. XNAME
  26. X     make - maintain, update, and reconstruct groups of programs
  27. X
  28. XSYNOPSIS
  29. X     make [-f makefile] [-dDeiknqrsSt] [target...] [macro=value ...]
  30. X
  31. XDESCRIPTION
  32. X     MAKE takes a file of dependencies (a 'makefile') and decides what
  33. X     commands have to be executed to bring the files up to date.  These
  34. X     commands are either executed directly from MAKE or written to the
  35. X     standard output without executing them.
  36. X
  37. X     If no makefile is specified with a -f option, MAKE reads a file
  38. X     named `makefile', if it exists.
  39. X
  40. X     If no target is specified on the command line, MAKE uses the first
  41. X     target defined in the first makefile.
  42. X
  43. XOPTIONS
  44. X     -f makefile
  45. X         Use the description file `makefile'.  A - as the makefile
  46. X         argument denotes the standard input.
  47. X
  48. X     -d  Display the reasons why MAKE chooses to rebuild a target.  All
  49. X         dependencies which are newer are displayed
  50. X
  51. X     -dd Display the dependency checks in more detail.  Dependencies
  52. X         which are older are displayed, as well as newer.
  53. X
  54. X     -D  Display the text of the makefiles as read in.
  55. X
  56. X     -DD Display the text of the makefiles and `default.mk'.
  57. X
  58. X     -e  Let environment variables override macro definitions from
  59. X         makefiles.  Normally, makefile macros override environment
  60. X         variables.  Command line macro definitions always override both
  61. X         environment variables and makefile macros definitions.
  62. X
  63. X     -i  Ignore error codes returned by commands.  This is equivalent to
  64. X         the special target .IGNORE:.
  65. X
  66. X     -k  When a nonzero error status is returned by a command, abandon
  67. X         work on the current target, but continue with other branches
  68. X         that do not depend on this target.
  69. X
  70. X     -n  No execution mode.  Print commands, but do not execute them.
  71. X         Even lines beginning with an @ are printed.  However, if a
  72. X         command line is an invocation of MAKE, that line is always
  73. X         executed.
  74. X
  75. X     -q  Question mode.  MAKE returns a zero or non-zero status code,
  76. X         depending on whether or not the target file is up to date.
  77. X
  78. X     -r  Do not read in the default file `default.mk'.
  79. X
  80. X     -s  Silent mode.  Do not print command lines before executing them.
  81. X         This is equivalent to the special target .SILENT:.
  82. X
  83. X     -S  Undo the effect of the -k option.  Stop processing when a
  84. X         non-zero exit status is returned by a command.
  85. X
  86. X     -t  Touch the target files, bringing them up to date, rather than
  87. X         performing the rules to reconstruct them.
  88. X
  89. X     macro=value
  90. X         Macro definition.  This definition remains fixed for the MAKE
  91. X         invocation.  It overrides any regular definitions for the
  92. X         specified macro within the makefiles and from the environment.
  93. X         It is inherited by subordinate MAKE's but act as an environment
  94. X         variable for these.  That is, depending on the -e setting, it
  95. X         may be overridden by a makefile definition.
  96. X
  97. XUSAGE
  98. X  Makefiles
  99. X     The first makefile read is `default.mk', which can be located any-
  100. X     where along the PATH.  It typically contains predefined macros and
  101. X     implicit rules.  For non-DOS systems (e.g. Unix), it is searched
  102. X     for in the current directory, then in the users home directory, and
  103. X     finally along the PATH.
  104. X
  105. X     The default name of the makefile is `makefile' in the current
  106. X     directory.  If this file is not found on a non-DOS system, the file
  107. X     `Makefile' is then used as the default.  Alternate makefiles can be
  108. X     specified using one or more '-f' options on the command line.
  109. X     Multiple '-f's act as the concatenation of all the makefiles in a
  110. X     left-to-right order.
  111. X
  112. X     The makefile(s) may contain a mixture of comment lines, macro
  113. X     definitions, include lines, and target lines.  Lines may be
  114. X     continued across input lines by escaping the NEWLINE with a
  115. X     backslash (\).
  116. X
  117. X     Anything after a "#" is considered to be a comment, and is stripped
  118. X     from the line, including spaces immediately before the "#.
  119. X     Completely blank lines are ignored.
  120. X
  121. X     An include line is used to include the text of another makefile.
  122. X     It consists of the word "include" left justified, followed by
  123. X     spaces, and followed by the name of the file that is to be included
  124. X     at this line.  Include files may be nested.
  125. X
  126. X  Macros
  127. X     Macros have the form `WORD = text and more text'.  The WORD need
  128. X     not be uppercase, but this is an accepted standard.  Later lines
  129. X     which contain $(WORD) or ${WORD} will have this replaced by `text
  130. X     and more text'.  If the macro name is a single character, the
  131. X     parentheses are optional.  Note that the expansion is done
  132. X     recursively, so the body of a macro may contain other macro
  133. X     invocations.
  134. X
  135. X    e.g.    FLINTSTONES = wilma and fred
  136. X        RUBBLES = barney and betty
  137. X        BEDROCK = $(FLINTSTONES) and $(RUBBLES)
  138. X
  139. X     `$(BEDROCK)' becomes `wilma and fred and barney and betty'
  140. X
  141. X     Also note that whitespace around the equal sign is not relevant
  142. X     when defining a macro.  The following four macro definitions are
  143. X     all equivalent:
  144. X
  145. X        MACRO = body
  146. X        MACRO=  body
  147. X        MACRO  =body
  148. X        MACRO=body
  149. X
  150. X     Macros may be added to by using the `+=' notation.  Thus
  151. X
  152. X        FLINTSTONES += and pebbles and dino
  153. X
  154. X     would be (given the examples above) the same as
  155. X
  156. X        FLINTSTONES = wilma and fred and pebbles and dino
  157. X
  158. X  Special Macros
  159. X     MAKE
  160. X         This normally has the value "make".  Any line which invokes
  161. X         MAKE temporarily overrides the -n option, just for the duration
  162. X         of the one line.  This allows nested invocations of MAKE to be
  163. X         tested with the -n option.
  164. X
  165. X     MAKEFLAGS
  166. X         This macro has the set of options provided to MAKE as its
  167. X         value.  If this is set as an environment variable, the set of
  168. X         options is processed before any command line options.  This
  169. X         macro may be explicitly passed to nested MAKEs, but it is also
  170. X         available to these invocations as an environment variable.  The
  171. X     -f and -d flags are not recorded in this macro.
  172. X
  173. X     SUFFIXES
  174. X         This contains the default list of suffixes supplied to the
  175. X         special target .SUFFIXES:.  It is not sufficient to simply
  176. X         change this macro in order to change the .SUFFIXES: list.  That
  177. X         target must be specified in your makefile.
  178. X
  179. X     There are several dynamically maintained macros that are useful as
  180. X     abbreviations within rules.  It is best not to define them
  181. X     explicitly.
  182. X
  183. X     $*  The basename of the current target.
  184. X
  185. X     $<  The name of the current dependency file.
  186. X
  187. X     $@  The name of the current target.
  188. X
  189. X     The $< and $* macros are normally used for implicit rules.  They
  190. X     may be unreliable when used within explicit target command lines.
  191. X     These may be suffixed with D and F, to specify the Directory and
  192. X     Filename components (e.g. ${*D}, ${@F}).  If there is no directory
  193. X     in the name, "." is supplied.
  194. X
  195. X  Targets
  196. X     A target entry in the makefile has the following format:
  197. X
  198. X    target ... : [dependency ...] [; rule]
  199. X        [rule]
  200. X        ...
  201. X
  202. X     Any line which does not have leading whitespace (other than macro
  203. X     definitions) is a `target' line.  Target lines consist of one or
  204. X     more filenames (or macros which expand into same) called targets,
  205. X     followed by a colon (:).  The ':' is followed by a list of
  206. X     dependent files.  The dependency list may be terminated with a
  207. X     semicolon (;) which may be followed by a rule or shell command.
  208. X
  209. X     Special allowance is made on MSDOS for the colons which are needed
  210. X     to specify files on other drives, so for example, the following
  211. X     will work as intended:
  212. X
  213. X        c:foo.bar : a:fee.ber
  214. X
  215. X     If a target is named in more than one target line, the dependencies
  216. X     and rules are added to form the target's complete dependency list
  217. X     and rule list.
  218. X
  219. X     The dependents are ones from which a target is constructed.  They
  220. X     in turn may be targets of other dependents.  In general, for a
  221. X     particular target file, each of its dependent files is `made', to
  222. X     make sure that each is up to date with respect to it's dependents.
  223. X
  224. X     The modification time of the target is compared to the modification
  225. X     times of each dependent file.  If the target is older, one or more
  226. X     of the dependents have changed, so the target must be constructed.
  227. X     Of course, this checking is done recursively, so that all
  228. X     dependents of dependents of dependents of ...  are up to date.
  229. X
  230. X     To reconstruct a target, MAKE expands macros, strips off initial
  231. X     whitespace, and either executes the rules directly, or passes each
  232. X     to a shell or COMMAND.COM for execution.
  233. X
  234. X     For target lines, macros are expanded on input.  All other lines
  235. X     have macro expansion delayed until absolutely required.
  236. X
  237. X  Special Targets
  238. X     .DEFAULT:
  239. X         The rule for this target is used to process a target when there
  240. X         is no other entry for it, and no implicit rule for building it.
  241. X         MAKE ignores all dependencies for this target.
  242. X
  243. X     .DONE:
  244. X         This target and its dependencies are processed after all other
  245. X         targets are built.
  246. X
  247. X     .IGNORE:
  248. X         Non-zero error codes returned from commands are ignored.
  249. X         Encountering this in a makefile is the same as specifying -i on
  250. X         the command line.
  251. X
  252. X     .INIT:
  253. X         This target and its dependencies are processed before any other
  254. X         targets are processed.
  255. X
  256. X     .SILENT:
  257. X         Commands are not echoed before executing them.  Encountering
  258. X         this in a makefile is the same as specifying -s on the command
  259. X         line.
  260. X
  261. X     .SUFFIXES:
  262. X         The suffixes list for selecting implicit rules.  Specifying
  263. X         this target with dependents adds these to the end of the
  264. X         suffixes list.  Specifying it with no dependents clears the
  265. X         list.  In order to add your own dependents to the head of the
  266. X         list, you could enter:
  267. X
  268. X        .SUFFIXES:
  269. X        .SUFFIXES:    .abc $(SUFFIXES)
  270. X
  271. X  Rules
  272. X     A line in a makefile that starts with a TAB or SPACE is a shell
  273. X     line or rule.  This line is associated with the most recently
  274. X     preceding dependency line.  A sequence of these may be associated
  275. X     with a single dependency line.  When a target is out of date with
  276. X     respect to a dependent, the sequence of commands is executed.
  277. X     Shell lines may have any combination of the following characters to
  278. X     the left of the command:
  279. X
  280. X     @   will not echo the command line, except if -n is used.
  281. X
  282. X     -   MAKE will ignore the exit code of the command, i.e.  the
  283. X         ERRORLEVEL of MSDOS.  Without this, MAKE terminates when a
  284. X         nonzero exit code is returned.
  285. X
  286. X     +   MAKE will use a shell or COMMAND.COM to execute the command.
  287. X
  288. X     If the '+' is not attached to a shell line, but the command is a
  289. X     DOS command or if redirection is used (<, |, >), the shell line is
  290. X     passed to COMMAND.COM anyway.  For Unix, redirection and backquote
  291. X     (`) force the use of a shell.
  292. X
  293. X  Implicit Rules
  294. X     Implicit rules are intimately tied to the .SUFFIXES: special
  295. X     target.  Each entry in the .SUFFIXES defines an extension to a
  296. X     filename which may be used to build another file.  The implicit
  297. X     rules then define how to actually build one file from another.
  298. X     These files are related, in that they must share a common basename,
  299. X     but have different extensions.
  300. X
  301. X     If a file that is being made does not have an explicit target line,
  302. X     an implicit rule is looked for.  Each entry in the .SUFFIXES: list
  303. X     is combined with the extension of the target, to get the name of an
  304. X     implicit target.  If this target exists, it gives the rules used to
  305. X     transform a file with the dependent extension to the target file.
  306. X     Any dependents of the implicit target are ignored.
  307. X
  308. X     In the following example, the .SUFFIXES: list is .c .y .l, and the
  309. X     target file is fred.o which does not have a target line.  An
  310. X     implicit rule target `.c.o' is constructed and searched for.  If it
  311. X     does not exist, the next suffix is tried.  If the implicit rule
  312. X     target does exist, MAKE looks for a file `fred.c'.  If this file
  313. X     does not exist, the next extension is tried.  If `fred.c' does
  314. X     exist, then the associated rules are executed to create fred.o from
  315. X     fred.c, presumably invoking the C compiler.
  316. X
  317. X     If the next extension must be tried, MAKE reiterates the above with
  318. X     target `.y.o' and a file named `fred.y', and potentially with
  319. X     `.l.o' and `fred.l'.
  320. X
  321. X     If a file that is being made has an explicit target, but no rules,
  322. X     a similar search is made for implicit rules.  Each entry in the
  323. X     .SUFFIXES: list is combined with the extension of the target, to
  324. X     get the name of an implicit target.  If such a target exists, then
  325. X     the list of dependents is searched for a file with the correct
  326. X     extension, and the implicit rules are invoked to create the target.
  327. X
  328. XEXAMPLES
  329. X     This makefile says that pgm.exe depends on two files a.obj and
  330. X     b.obj, and that they in turn depend on their corresponding source
  331. X     files (a.c and b.c) along with the common file incl.h.
  332. X
  333. X    pgm.exe: a.obj b.obj
  334. X        $(CC) a.obj b.obj -o $@
  335. X
  336. X    a.obj:    incl.h a.c
  337. X        $(CC) -c a.c
  338. X
  339. X    b.obj:    incl.h b.c
  340. X        $(CC) -c b.c
  341. X
  342. X     The following makefile uses implicit rules to express the same
  343. X     dependencies.
  344. X
  345. X    pgm.exe: a.obj b.obj
  346. X        $(CC) a.obj b.obj -o $@
  347. X
  348. X    a.obj b.obj: incl.h
  349. X
  350. X     This final makefile uses implicit rules to create targets with
  351. X     dependencies in a different directory.  Note: this cannot be done
  352. X     with standard Unix make.
  353. X
  354. X    pgm.exe: a.obj b.obj
  355. X        $(CC) a.obj b.obj -o $@
  356. X
  357. X    a.obj:    incl.h ../a.c
  358. X
  359. X    b.obj:    incl.h ../b.c
  360. X
  361. XFILES
  362. X     makefile            Current version(s) of make description file.
  363. X     Makefile            Alternative to makefile, for Unix.
  364. X     default.mk          Default file for user-defined targets, macros,
  365. X                         and implicit rules.
  366. X
  367. XDIAGNOSTICS
  368. X     MAKE returns an exit status of 1 when it halts as a result of an
  369. X     error.  Otherwise it returns an exit status of 0.
  370. X
  371. X     Badly formed macro
  372. X         A macro definition has been encountered which has incorrect
  373. X         syntax.  Most likely, the name is missing.
  374. X
  375. X     cannot open file
  376. X         The makefile indicated in an include directive was not found or
  377. X         was not accessible.
  378. X
  379. X     Don't know how to make target
  380. X         There is no makefile entry for target, none of MAKE's implicit
  381. X         rules apply, and there is no .DEFAULT: rule.
  382. X
  383. X     Improper Macro.
  384. X         An error has occurred during macro expansion.  The most likely
  385. X         error is a missing closing bracket.
  386. X
  387. X     Macro too long (limit 100 chars):
  388. X         A macro name is too long for the internal buffer.  Try shortening
  389. X     it to 100 characters or less.
  390. X
  391. X     rules must be after target
  392. X         A makefile syntax error, where a line beginning with a SPACE or
  393. X         TAB has been encountered before a target line.
  394. X
  395. X     too many options
  396. X         MAKE has run out of allocated space while processing command
  397. X         line options or a target list.
  398. X
  399. X     Too many rules defined for target
  400. X     A target occurs multiple times, and each time has rules.  A
  401. X     target may only have one set of rules.
  402. X
  403. X     Unexpected end of line seen
  404. X         A target line without a colon has been encountered.
  405. X
  406. XAUTHOR
  407. X     Greg Yachuk    Informix Software Inc., Menlo Park CA 94025
  408. X     {pyramid,uunet}!infmx!greggy             (415) 926-6300
  409. X
  410. X     Parts of this program are based on the work by Larry Campbell of
  411. X     DEC, Mike Hickey of University of DC, and by Dan Grayson.
  412. X
  413. X     Some of this documentation is based on text written by Jeffrey
  414. X     Spidle of Iowa State University and by Dan Grayson.
  415. X
  416. X     Some of the formatting of this documentation follows the example of
  417. X     Sun Microsystems for their UNIX 4.2 Release.
  418. X
  419. XBUGS
  420. X     MAKE allows spaces as well as TABs to introduce shell command
  421. X     lines.
  422. X
  423. X     Target lines cannot use the double colon (::) syntax.
  424. X
  425. X     Once a dependency is made, MAKE assumes that the dependency file is
  426. X     present for the remainder of the run.  If a rule subsequently
  427. X     removes that file and future targets depend on it's existence,
  428. X     unexpected errors may result.
  429. X
  430. X     Sometimes MAKE gets confused when searching for implicit rules, and
  431. X     uses several rules instead of a single rule.  For example, the two
  432. X     rules .c.o and .l.c may be used, rather than the more direct .l.o
  433. X     rule.
  434. X
  435. X     If a number of command line flags are run together, and contains
  436. X     either `f' or `d', the whole set of flags is dropped from
  437. X     MAKEFLAGS.
  438. X
  439. X     The following flags are NOT supported:
  440. X
  441. X     -p  Print out the compete set of macro definitions and target
  442. X         descriptions.
  443. X
  444. X     -P  Report dependencies recursively to show the entire dependency
  445. X         hierarchy, without rebuilding any targets.
  446. X
  447. X     The following special targets are NOT supported:
  448. X
  449. X     .KEEP_STATE:
  450. X     .MAKE_VERSION:
  451. X     .PRECIOUS:
  452. X     .SCCS_GET:
  453. END_OF_FILE
  454. if test 17010 -ne `wc -c <'make.doc'`; then
  455.     echo shar: \"'make.doc'\" unpacked with wrong size!
  456. fi
  457. # end of 'make.doc'
  458. fi
  459. if test -f 'parse.c' -a "${1}" != "-c" ; then 
  460.   echo shar: Will not clobber existing file \"'parse.c'\"
  461. else
  462. echo shar: Extracting \"'parse.c'\" \(16977 characters\)
  463. sed "s/^X//" >'parse.c' <<'END_OF_FILE'
  464. X/*
  465. X * parse.c
  466. X *
  467. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  468. X * 88-10-06 v1.1    changed prerequisite list handling
  469. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  470. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  471. X * 89-08-01 v1.4 AB    lots of new options and code
  472. X * 89-10-30 v1.5 greggy    -f -S -q options, took some changes from v1.4
  473. X *
  474. X */
  475. X#include <stdio.h>
  476. X#include <ctype.h>
  477. X#include <string.h>
  478. X#ifdef    MSDOS
  479. X#include <stdlib.h>
  480. X#endif
  481. X
  482. X#include "make.h"
  483. X#include "tstring.h"
  484. X#include "decl.h"
  485. X
  486. X/*
  487. X * parse    - read (text) makefile, and parse
  488. X *        - close file before returing
  489. X *
  490. X * lines have the following format:
  491. X *    # with or without preceeding spaces/tabs    (comment line)
  492. X *    <TAB> commands                    (shell line)
  493. X *    name = stuff                    (macro)
  494. X *    name += stuff                    (macro)
  495. X *    targ [targ...] : [pre-req...] [; shell cmd ]    (target line)
  496. X */
  497. Xparse(fd)
  498. XFILE   *fd;
  499. X{
  500. X    char   *input;
  501. X    char   *ip;
  502. X    char   *colonp;
  503. X    char    schar;
  504. X    int     ntargs, npreqs, nshell;
  505. X    int     tmax, pmax, smax;
  506. X    targptr *targs;
  507. X    fileptr *preqs;
  508. X    shellptr *shells;
  509. X
  510. X    if (fd == NULL)
  511. X        return (0);
  512. X
  513. X    /* start off with a short list of targets */
  514. X    targs = (targptr *) grow_list(NULL, &tmax);
  515. X    preqs = (fileptr *) grow_list(NULL, &pmax);
  516. X    shells = (shellptr *) grow_list(NULL, &smax);
  517. X
  518. X    ntargs = npreqs = nshell = 0;
  519. X
  520. X    /* maximize buffering */
  521. X    setvbuf(fd, NULL, _IOFBF, 2048);
  522. X
  523. X    while ((input = tgets(fd)) != NULL)
  524. X    {
  525. X        /* punt on comments and blank lines */
  526. X        for (ip = input; isspace(*ip); ++ip);
  527. X        if (*ip == '#' || *ip == '\0')
  528. X            continue;
  529. X
  530. X        /* process include files */
  531. X        if (!strncmp(ip, "include", 7))
  532. X        {
  533. X            /* skip spaces AFTER "include" */
  534. X            for (ip += 7; isspace(*ip); ++ip);
  535. X            if (!parse(fopen(ip, "r")))
  536. X                terror(1, tstrcat("cannot open ", ip));
  537. X            continue;    /* get next input line */
  538. X        }
  539. X
  540. X        /* display the makefile line ? */
  541. X        if (opts.display)
  542. X            puts(input);
  543. X
  544. X        /* get rid of comments and preceeding spaces */
  545. X        for (colonp = ip; *colonp && *colonp != '#'; ++colonp)
  546. X        {
  547. X            if (*colonp == '\'' || *colonp == '"')
  548. X                colonp = tstrspan(colonp);
  549. X        }
  550. X
  551. X        for (--colonp; colonp >= ip && isspace(*colonp); --colonp);
  552. X
  553. X        /* we *know* that some non-space is on this line, from above */
  554. X        if (colonp >= ip)
  555. X            *++colonp = '\0';
  556. X
  557. X        /* see if we have a shell command */
  558. X        if (isspace(*input))
  559. X        {
  560. X            if (ntargs == 0)
  561. X                terror(1, "rules must be after target");
  562. X    got_shell:
  563. X            if (nshell == smax)
  564. X            {
  565. X                shells = (shellptr *)
  566. X                    grow_list((char **) shells, &smax);
  567. X            }
  568. X            shells[nshell++] = add_shell(ip);
  569. X            continue;
  570. X        }
  571. X
  572. X        /* not a shell line, so must be a target or a macro */
  573. X        if (ntargs != 0)
  574. X        {
  575. X            /* link previous preq's and shell's */
  576. X            targs[ntargs] = NULL;
  577. X            preqs[npreqs] = NULL;
  578. X            shells[nshell] = NULL;
  579. X            link_targs(targs, preqs, shells);
  580. X            ntargs = npreqs = nshell = 0;
  581. X        }
  582. X
  583. X        /* don't break out symbols until macro is invoked */
  584. X        if (add_macro(ip, 0))
  585. X            continue;
  586. X
  587. X        /* okay, we have a target line; break out macro symbols */
  588. X        input = breakout(ip);
  589. X
  590. X        /* just look for tokens with standard isspace() separators */
  591. X        ip = token(input, NULL, &schar);
  592. X        while (ip)
  593. X        {
  594. X            colonp = strchr(ip, ':');
  595. X#ifdef    MSDOS
  596. X            /* need to allow c:/bin/make.exe as a target */
  597. X            if (colonp && colonp - ip == 1)
  598. X                colonp = strchr(colonp + 1, ':');
  599. X#endif
  600. X            if (colonp)
  601. X            {
  602. X                /* got a separator */
  603. X                *colonp = '\0';
  604. X
  605. X                /* if at front of token, target is done */
  606. X                if (colonp == ip)
  607. X                    break;
  608. X            }
  609. X
  610. X            if (ntargs == tmax)
  611. X                targs = (targptr *) grow_list((char **) targs,
  612. X                                  &tmax);
  613. X            targs[ntargs] = add_target(ip);
  614. X
  615. X            /* make sure we don't save .INIT as our 1st target */
  616. X            if (first_targ == NULL && *ip != '.')
  617. X                first_targ = targs[ntargs];
  618. X            ++ntargs;
  619. X
  620. X            if (colonp)
  621. X                break;
  622. X            ip = token(NULL, NULL, &schar);
  623. X        }
  624. X
  625. X        /* a target line without a colon?  naughty, naughty! */
  626. X        if (!colonp)
  627. X            terror(-1, "Unexpected end of line seen");
  628. X
  629. X/*
  630. X * taking care of four possible cases:
  631. X *    1)    object : source
  632. X *    2)    object: source
  633. X *    3)    object :source
  634. X *    4)    object:source
  635. X */
  636. X
  637. X        if (colonp && *++colonp)
  638. X            ip = colonp;
  639. X        else
  640. X            ip = token(NULL, NULL, &schar);
  641. X
  642. X        /* link the pre-req's */
  643. X        while (ip)
  644. X        {
  645. X            if ((colonp = strchr(ip, ';')) != NULL)
  646. X            {
  647. X                ip[strlen(ip)] = schar;
  648. X                *colonp = '\0';
  649. X            }
  650. X
  651. X            if (*ip)
  652. X            {
  653. X                if (npreqs == pmax)
  654. X                {
  655. X                    preqs = (fileptr *)
  656. X                        grow_list((char **) preqs,
  657. X                              &pmax);
  658. X                }
  659. X
  660. X                preqs[npreqs++] = add_file(ip);
  661. X            }
  662. X
  663. X            if (colonp)
  664. X            {
  665. X                ip = colonp + 1;
  666. X                goto got_shell;
  667. X            }
  668. X
  669. X            ip = token(NULL, NULL, &schar);
  670. X        }
  671. X
  672. X        /* gotta free the line allocated by breakout() */
  673. X        tfree(input);
  674. X    }
  675. X
  676. X    /* link up any dangling dependants */
  677. X    if (ntargs != 0)
  678. X    {
  679. X        targs[ntargs] = NULL;
  680. X        preqs[npreqs] = NULL;
  681. X        shells[nshell] = NULL;
  682. X        link_targs(targs, preqs, shells);
  683. X    }
  684. X
  685. X    /* clean up our mallocs */
  686. X    tfree(targs);
  687. X    tfree(preqs);
  688. X    tfree(shells);
  689. X
  690. X    fclose(fd);
  691. X    return (1);
  692. X}
  693. X
  694. X
  695. X/*
  696. X * link_targs    - force a list of targs to point to same preq's and shell's
  697. X */
  698. Xlink_targs(targs, preqs, shells)
  699. XREGISTER targptr *targs;
  700. Xfileptr *preqs;
  701. Xshellptr *shells;
  702. X{
  703. X    while (targs && *targs)
  704. X    {
  705. X        /* process some special targets */
  706. X        if ((*targs)->tfile->fname[0] == '.')
  707. X        {
  708. X            if (equal((*targs)->tfile->fname, ".SILENT"))
  709. X                opts.silent = 1;
  710. X            else if (equal((*targs)->tfile->fname, ".IGNORE"))
  711. X                opts.ignore = 1;
  712. X            else if (equal((*targs)->tfile->fname, ".SUFFIXES"))
  713. X                /*
  714. X                 * set `suffix_targ' to speed up
  715. X                 * `default_rule'
  716. X                 */
  717. X                suffix_targ = *targs;
  718. X
  719. X            /* special rule has preq's reset */
  720. X            /* normally, preq's are merely appended */
  721. X            if (*preqs == NULL && (*targs)->tpreq != NULL)
  722. X            {
  723. X                tfree((*targs)->tpreq);
  724. X                (*targs)->tpreq = NULL;
  725. X            }
  726. X
  727. X            /* special rules have their shell commands replaced */
  728. X            if ((*targs)->tshell != NULL && *shells != NULL)
  729. X            {
  730. X                shellptr *sp;
  731. X
  732. X                for (sp = (*targs)->tshell; *sp; ++sp)
  733. X                    tfree(*sp);
  734. X                tfree((*targs)->tshell);
  735. X                (*targs)->tshell = NULL;
  736. X            }
  737. X        }
  738. X
  739. X        /* each target in the list points to the preq's and shell's */
  740. X        (*targs)->tpreq = append_preq((*targs)->tpreq, preqs);
  741. X
  742. X        /* we cannot expand the list of shell commands */
  743. X        if ((*targs)->tshell != NULL && *shells != NULL)
  744. X        {
  745. X            terror(1, tstrcat("Too many rules defined for target ",
  746. X                      (*targs)->tfile->fname));
  747. X        }
  748. X        (*targs)->tshell = append_shell((*targs)->tshell, shells);
  749. X        ++targs;
  750. X    }
  751. X}
  752. X
  753. X
  754. X/* macros must have the format: WORD = more stuff
  755. X *                     WORD= more stuff
  756. X *                WORD =more stuff
  757. X *                WORD=more stuff
  758. X *            or:    WORD += more stuff
  759. X *                WORD +=more stuff
  760. X *
  761. X * it is assumed that there is no leading whitespace in `input'
  762. X */
  763. Xadd_macro(input, scmd)
  764. Xchar   *input;
  765. Xint     scmd;
  766. X{
  767. X    REGISTER char *eqsign;
  768. X    REGISTER char *value;
  769. X    symptr  symp;
  770. X
  771. X    /* gotta have an '=' to be a macro */
  772. X    eqsign = strchr(input, '=');
  773. X    if (eqsign == NULL)
  774. X        return (0);
  775. X
  776. X    /* make sure we catch imbedded '='s (e.g. MACRO=STUFF) */
  777. X    for (value = input; *value && !isspace(*value); ++value);
  778. X    if (value > eqsign)
  779. X        value = eqsign;
  780. X
  781. X    /* terminate the macro name */
  782. X    *value = '\0';
  783. X
  784. X    /* find start of value */
  785. X    for (value = eqsign + 1; isspace(*value); ++value);
  786. X
  787. X    /* look for concat character */
  788. X    --eqsign;
  789. X
  790. X    if (eqsign < input || (eqsign == input && *eqsign == '+'))
  791. X        terror(1, "Badly formed macro");
  792. X
  793. X    if (*eqsign == '+')
  794. X    {
  795. X        /* append to the current macro definition */
  796. X        *eqsign = '\0';
  797. X        symp = get_symbol(input, scmd);
  798. X        if (symp->scmd && !scmd)
  799. X            return (1);
  800. X        if (symp->slevel < make_level)
  801. X            symp = dup_symbol(symp, symp->svalue);
  802. X        if (symp->svalue)
  803. X        {
  804. X            eqsign = tstrcat(symp->svalue, " ");
  805. X            value = tstrcat(eqsign, value);
  806. X            tfree(eqsign);
  807. X            tfree(symp->svalue);
  808. X            symp->svalue = value;
  809. X            return (1);
  810. X        }
  811. X    }
  812. X
  813. X    add_symbol(input, value, scmd);
  814. X    return (1);
  815. X}
  816. X
  817. X
  818. X/*
  819. X * add_symbol    - add a <name,value> pair to the symbol table
  820. X *        - override existing symbol value
  821. X *        - mark as either command-line macro or not
  822. X */
  823. Xadd_symbol(name, value, scmd)
  824. Xchar   *name;
  825. Xchar   *value;
  826. Xint     scmd;
  827. X{
  828. X    REGISTER symptr symp;
  829. X
  830. X    symp = get_symbol(name, scmd);
  831. X    if (symp->scmd & !scmd)
  832. X        return;
  833. X    if (symp->slevel < make_level)
  834. X        symp = dup_symbol(symp, NULL);    /* don't dup the value */
  835. X    if (symp->svalue)
  836. X        tfree(symp->svalue);
  837. X    symp->svalue = tstrcpy(value);
  838. X    symp->scmd = scmd;
  839. X}
  840. X
  841. X
  842. X/*
  843. X * get_symbol    - find a symbol in the symbol table
  844. X *        - if non-extant, create <name,NULL>
  845. X *        - return created or found symbol node
  846. X */
  847. Xsymptr
  848. Xget_symbol(name, scmd)
  849. Xchar   *name;
  850. Xint     scmd;
  851. X{
  852. X    REGISTER symptr symp;
  853. X    REGISTER t_mask mask;
  854. X    char   *np;
  855. X
  856. X    /* use `mask' to screen out most string comparisons */
  857. X    mask = 0;
  858. X    np = name;
  859. X    while (*np)
  860. X        mask += *np++;
  861. X
  862. X    /* linear search through symbol list */
  863. X    for (symp = symbol_list; symp != NULL; symp = symp->snext)
  864. X    {
  865. X        if (mask != symp->smask)
  866. X            continue;
  867. X
  868. X        if (equal(name, symp->sname))
  869. X            return (symp);
  870. X    }
  871. X
  872. X    symp = tnew(symnode);    /* allocate symbol node */
  873. X    symp->smask = mask;    /* record mask for later */
  874. X    symp->sname = tstrcpy(name);    /* allocate string and copy name */
  875. X    symp->scmd = scmd;    /* command line macro? */
  876. X    symp->slevel = make_level;    /* current new_make() level */
  877. X
  878. X    /* get the value from the environment, if it is there */
  879. X
  880. X    if ((symp->svalue = getenv(name)) != NULL)
  881. X    {
  882. X        symp->svalue = tstrcpy(symp->svalue);
  883. X
  884. X        /*
  885. X         * if `-e', let command line macros override, but not macro
  886. X         * assignments in the makefile.
  887. X         */
  888. X        if (opts.envirn)
  889. X            symp->scmd = 1;
  890. X    }
  891. X
  892. X    symp->snext = symbol_list;    /* link to head of symbol list */
  893. X    symbol_list = symp;
  894. X
  895. X    return (symp);
  896. X}
  897. X
  898. X
  899. X/*
  900. X * dup_sym    - duplicate a symbol node, but at current new_make() level
  901. X */
  902. Xsymptr
  903. Xdup_symbol(sp, svalue)
  904. Xsymptr  sp;
  905. Xchar   *svalue;
  906. X{
  907. X    symptr  nsp;
  908. X
  909. X    nsp = tnew(symnode);    /* allocate symbol node */
  910. X    nsp->smask = sp->smask;    /* record mask for later */
  911. X    nsp->sname = tstrcpy(sp->sname);    /* allocate string and copy
  912. X                         * name */
  913. X    nsp->svalue = (svalue == NULL) ? NULL : tstrcpy(svalue);
  914. X    nsp->scmd = sp->scmd;    /* command line macro? */
  915. X    nsp->slevel = make_level;    /* current new_make() level */
  916. X
  917. X    nsp->snext = symbol_list;    /* link to head of symbol list */
  918. X    symbol_list = nsp;
  919. X
  920. X    return (nsp);
  921. X}
  922. X
  923. X
  924. X/*
  925. X * add_target    - return extant target node, or create new one
  926. X */
  927. Xtargptr
  928. Xadd_target(name)
  929. Xchar   *name;
  930. X{
  931. X    t_mask  mask;
  932. X    REGISTER targptr targp;
  933. X    fileptr filep;
  934. X
  935. X    /* each target must have a file node */
  936. X    filep = add_file(name);
  937. X
  938. X    /* see if target already exists */
  939. X    targp = hash_target(name, &mask);
  940. X    if (targp)
  941. X        return (targp);
  942. X
  943. X    /* oh well, gotta create one */
  944. X    targp = tnew(targnode);    /* allocate a target node */
  945. X    targp->tmask = mask;    /* save mask for later */
  946. X    targp->tfile = filep;    /* save pointer to file node */
  947. X    targp->tpreq = NULL;    /* no pre-req's yet */
  948. X    targp->tshell = NULL;    /* no shell lines yet */
  949. X
  950. X    targp->tnext = target_list;    /* link to front of target list */
  951. X    target_list = targp;
  952. X
  953. X    return (targp);
  954. X}
  955. X
  956. X
  957. X/*
  958. X * hash_target    - look up target (by name) in target list
  959. X *        - return target node or NULL
  960. X *        - if requested, also return the mask
  961. X */
  962. Xtargptr
  963. Xhash_target(name, maskp)
  964. Xchar   *name;
  965. Xt_mask *maskp;
  966. X{
  967. X    REGISTER targptr targp;
  968. X    REGISTER t_mask mask;
  969. X    char   *np;
  970. X
  971. X    /* use `mask' to screen out most string comparisons */
  972. X    mask = 0;
  973. X    np = name;
  974. X    while (*np)
  975. X        mask += *np++;
  976. X
  977. X    /* see if we gotta return it */
  978. X    if (maskp != NULL)
  979. X        *maskp = mask;
  980. X
  981. X    /* linear search through target list */
  982. X    for (targp = target_list; targp != NULL; targp = targp->tnext)
  983. X    {
  984. X        if (mask != targp->tmask)
  985. X            continue;
  986. X
  987. X        /* target name is ONLY stored in the file node */
  988. X        if (equal(name, targp->tfile->fname))
  989. X            return (targp);
  990. X    }
  991. X
  992. X    /* nope, no target here */
  993. X    return (NULL);
  994. X}
  995. X
  996. X
  997. X/*
  998. X * add_file    - return a found or created file node
  999. X */
  1000. Xfileptr
  1001. Xadd_file(name)
  1002. Xchar   *name;
  1003. X{
  1004. X    t_mask  mask;
  1005. X    REGISTER fileptr filep;
  1006. X
  1007. X    /* see if file node already exists */
  1008. X    filep = hash_file(name, &mask);
  1009. X    if (filep)
  1010. X        return (filep);
  1011. X
  1012. X    filep = tnew(filenode);    /* allocate new file node */
  1013. X    filep->fmask = mask;    /* save mask for later */
  1014. X    filep->fname = tstrcpy(name);    /* allocate string and copy name */
  1015. X    filep->ftime = MAXNEGTIME;    /* init MODIFY time to long time ago */
  1016. X
  1017. X    filep->fnext = file_list;    /* link to head of file list */
  1018. X    file_list = filep;
  1019. X
  1020. X    return (filep);
  1021. X}
  1022. X
  1023. X
  1024. X/*
  1025. X * hash_file    - look up file (by name) in file list
  1026. X *        - return file node or NULL
  1027. X *        - if requested, also return the mask
  1028. X */
  1029. Xfileptr
  1030. Xhash_file(name, maskp)
  1031. Xchar   *name;
  1032. Xt_mask *maskp;
  1033. X{
  1034. X    REGISTER fileptr filep;
  1035. X    REGISTER t_mask mask;
  1036. X    char   *np;
  1037. X
  1038. X    /* use `mask' to screen out most string comparisons */
  1039. X    mask = 0;
  1040. X    np = name;
  1041. X    while (*np)
  1042. X        mask += *np++;
  1043. X
  1044. X    /* see if we gotta return it */
  1045. X    if (maskp != NULL)
  1046. X        *maskp = mask;
  1047. X
  1048. X    /* linear search through file list */
  1049. X    for (filep = file_list; filep != NULL; filep = filep->fnext)
  1050. X    {
  1051. X        if (filep->fmask != mask)
  1052. X            continue;
  1053. X
  1054. X        if (equal(filep->fname, name))
  1055. X            return (filep);
  1056. X    }
  1057. X
  1058. X    /* nope, no file here */
  1059. X    return (NULL);
  1060. X}
  1061. X
  1062. X
  1063. X/*
  1064. X * append_node    - add a node to the end of an array of nodes
  1065. X */
  1066. Xchar  **
  1067. Xappend_node(node, adds, size)
  1068. Xchar  **node;
  1069. Xchar  **adds;
  1070. Xint     size;
  1071. X{
  1072. X    REGISTER int addlen, len;
  1073. X
  1074. X    for (addlen = 0; adds[addlen] != NULL; ++addlen);
  1075. X    if (addlen++ == 0)
  1076. X        return (node);
  1077. X
  1078. X    len = 0;
  1079. X
  1080. X    if (node != NULL)
  1081. X    {
  1082. X        for (; node[len] != NULL; ++len);
  1083. X        node = (char **) trealloc((char *) node, (len + addlen) * size);
  1084. X    }
  1085. X    else
  1086. X        node = (char **) talloc(addlen * size);
  1087. X
  1088. X    memcpy(node + len, adds, addlen * size);
  1089. X    return (node);
  1090. X}
  1091. X
  1092. X/*
  1093. X * add_shell    - create a new shell node, and add to end of given list
  1094. X */
  1095. Xshellptr
  1096. Xadd_shell(input)
  1097. Xchar   *input;
  1098. X{
  1099. X    REGISTER shellptr snode;
  1100. X
  1101. X    snode = tnew(shellnode);/* allocate a new shell node */
  1102. X    snode->s_shell = snode->s_ignore = snode->s_silent = 0;
  1103. X
  1104. X    for (; isspace(*input); ++input);    /* skip over leading spaces */
  1105. X    for (;; ++input)
  1106. X    {
  1107. X        if (*input == '+')
  1108. X            snode->s_shell = 1;    /* must use command.com */
  1109. X        else if (*input == '-')
  1110. X            snode->s_ignore = 1;    /* ignore return value */
  1111. X        else if (*input == '@')
  1112. X            snode->s_silent = 1;    /* don't echo command */
  1113. X        else
  1114. X            break;
  1115. X    }
  1116. X
  1117. X    snode->scmd = tstrcpy(input);    /* allocate string and copy command */
  1118. X
  1119. X    snode->slink = shell_list;    /* attach to global list */
  1120. X    shell_list = snode;
  1121. X
  1122. X    return (snode);
  1123. X}
  1124. X
  1125. X
  1126. X/*
  1127. X * breakout    - replace macro names with values
  1128. X *        - apply recursively
  1129. X * note: allocates (and returns) a string which must be freed
  1130. X */
  1131. Xchar   *
  1132. Xbreakout(input)
  1133. XREGISTER char *input;
  1134. X{
  1135. X    char   *dest, *dend;
  1136. X    REGISTER char *dp;
  1137. X    int     dlen;
  1138. X    int     tlen;
  1139. X    int     state;
  1140. X    char    symname[100];
  1141. X    char   *sp;
  1142. X    symptr  symp;
  1143. X    int     slen;
  1144. X    char    endch;
  1145. X
  1146. X    /* allocate a string twice as long as input string */
  1147. X
  1148. X    dlen = strlen(input) * 2;
  1149. X    dest = dp = talloc(dlen);
  1150. X    dend = dest + dlen;
  1151. X
  1152. X/*
  1153. X * state machine with 4 states
  1154. X *    0)    normal text    -- just copy
  1155. X *    1)    starting macro    -- define end char (e.g. ')', '}')
  1156. X *    2)    macro name    -- copy to a buffer
  1157. X *    3)    end of macro    -- look up value, and copy
  1158. X */
  1159. X    state = 0;
  1160. X
  1161. X    while (*input || state == 3)
  1162. X    {
  1163. X        /* if we don't have enough room, double size of string */
  1164. X        if (dp == dend)
  1165. X        {
  1166. X            dlen *= 2;
  1167. X            tlen = dp - dest;
  1168. X            dest = trealloc(dest, dlen);
  1169. X            dp = dest + tlen;
  1170. X            dend = dest + dlen;
  1171. X        }
  1172. X
  1173. X        switch (state)
  1174. X        {
  1175. X        case 0:
  1176. X            if (*input == '$')
  1177. X                state = 1;    /* found a macro */
  1178. X            else
  1179. X                *dp++ = *input++;
  1180. X            break;
  1181. X
  1182. X        case 1:
  1183. X            state = 2;    /* only in this state for 1 char */
  1184. X            sp = symname;
  1185. X            switch (*++input)
  1186. X            {
  1187. X            case '(':
  1188. X                endch = ')';
  1189. X                break;
  1190. X            case '{':
  1191. X                endch = '}';
  1192. X                break;
  1193. X            default:
  1194. X                /* single char; go to state 3 immediately */
  1195. X                *sp++ = *input;
  1196. X                state = 3;
  1197. X                break;
  1198. X            }
  1199. X            ++input;/* skip bracket (or character) */
  1200. X            break;
  1201. X
  1202. X        case 2:
  1203. X            if (*input == endch)
  1204. X                state = 3;
  1205. X            else
  1206. X                *sp++ = *input;
  1207. X
  1208. X            if ((sp - symname) >= (sizeof symname / sizeof symname[0]))
  1209. X            {
  1210. X                sp[-1] = '\0';
  1211. X                terror(1,
  1212. X                tstrcat("Macro too long (limit 100 chars): ",
  1213. X                    symname));
  1214. X            }
  1215. X
  1216. X            ++input;/* make sure we skip end char */
  1217. X            break;
  1218. X
  1219. X        case 3:
  1220. X            *sp = '\0';
  1221. X            symp = get_symbol(symname, 0);
  1222. X            sp = symp->svalue;
  1223. X            slen = -1;
  1224. X            while (sp && *sp)
  1225. X            {
  1226. X                /*
  1227. X                 * if value has a macro in it, we must
  1228. X                 * process recursively
  1229. X                 */
  1230. X                if (*sp == '$')
  1231. X                {
  1232. X                    sp = breakout(symp->svalue);
  1233. X                    /* now guaranteed not to have a '$' */
  1234. X                    slen = strlen(sp);
  1235. X                    break;
  1236. X                }
  1237. X                ++sp;
  1238. X            }
  1239. X
  1240. X            if (slen == -1)
  1241. X            {
  1242. X                /* value did NOT have a macro */
  1243. X                slen = (sp - symp->svalue);
  1244. X                sp = symp->svalue;
  1245. X            }
  1246. X
  1247. X            /* if we have not enough room, expand */
  1248. X            if (slen >= (dend - dp))
  1249. X            {
  1250. X                /* use slen to make sure that we can fit */
  1251. X                dlen = dlen * 2 + slen;
  1252. X                tlen = dp - dest;
  1253. X                dest = trealloc(dest, dlen);
  1254. X                dp = dest + tlen;
  1255. X                dend = dest + dlen;
  1256. X            }
  1257. X
  1258. X            /* if length is zero, don't bother to copy */
  1259. X            if (slen)
  1260. X            {
  1261. X                strcpy(dp, sp);
  1262. X                dp += slen;
  1263. X            }
  1264. X
  1265. X            if (sp != symp->svalue)
  1266. X                tfree(sp);    /* must've called `breakout' */
  1267. X
  1268. X            state = 0;    /* and we are back to text */
  1269. X            break;
  1270. X        }
  1271. X    }
  1272. X
  1273. X    if (state != 0)
  1274. X        terror(1, tstrcat("Improper macro.\n", dest));
  1275. X
  1276. X    *dp = '\0';        /* terminate the string */
  1277. X    return (dest);        /* and return it */
  1278. X}
  1279. END_OF_FILE
  1280. if test 16977 -ne `wc -c <'parse.c'`; then
  1281.     echo shar: \"'parse.c'\" unpacked with wrong size!
  1282. fi
  1283. # end of 'parse.c'
  1284. fi
  1285. echo shar: End of archive 2 \(of 3\).
  1286. cp /dev/null ark2isdone
  1287. MISSING=""
  1288. for I in 1 2 3 ; do
  1289.     if test ! -f ark${I}isdone ; then
  1290.     MISSING="${MISSING} ${I}"
  1291.     fi
  1292. done
  1293. if test "${MISSING}" = "" ; then
  1294.     echo You have unpacked all 3 archives.
  1295.     rm -f ark[1-9]isdone
  1296. else
  1297.     echo You still need to unpack the following archives:
  1298.     echo "        " ${MISSING}
  1299. fi
  1300. ##  End of shell archive.
  1301. exit 0
  1302.  
  1303.